#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/wait.h>

using namespace std;

void PrintSig(sigset_t &pending)
{
    cout<<"pending位图:";
    for(int signo=31;signo>=1;signo--)
    {
        if(sigismember(&pending,signo))
        {
            cout<<"1";
        }
        else
        {
            cout<<"0";
        }
    }
    cout<<endl;
}

void handler(int signo)
{
    //在2号信号递达之前，信号就已经被清0
    cout<<signo<<"号信号被递达"<<endl;
}

int main()
{
    //对2号信号进行自定义捕捉
    signal(2,handler);

    // 1.屏蔽2号信号
    sigset_t block,oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigaddset(&block,2);

    // 1.1 开始屏蔽2号信号，将其设置进内核
    int n=sigprocmask(SIG_SETMASK,&block,&oblock);
    assert(n==0);
    cout<<"block 2 signal success"<<endl;
    cout<<"pid:"<<getpid()<<endl;
    int cnt=0;
    while(true)
    {
        // 2.获取进程的pending位图
        sigset_t pending;
        sigemptyset(&pending);
        n=sigpending(&pending);
        assert(n==0);

        // 3.打印pending位图中的信号
        PrintSig(pending);
        cnt++;

        // 4.解除对2号信号的屏蔽
        if(cnt==20)
        {
            cout<<"解除对2号信号的屏蔽"<<endl;
            n=sigprocmask(SIG_UNBLOCK,&block,&oblock);//2号信号被立即抵达，终止进程
            assert(n==0);
        }
        sleep(1);
    }






















    // 没有涉及到将数据设置进内核
    // sigset_t类型和int， double没有区别
    // sigset_t s; //只是在用户栈上开辟了空间
    // sigemptyset(&s);
    // sigaddset(&s,2);

    // pid_t id=fork();
    // if(id == 0)
    // {
    //     //child
    //     sleep(1);
    //     int a=10;
    //     a /= 1;
    //     exit(0);
    // }
    // //father
    // int status=0;
    // pid_t rid=waitpid(id,&status,0);
    // if(rid>0)
    // {
    //     cout<<"exit code:"<<((status>>8) & 0xFF)<<endl;
    //     cout<<"exit signal:"<<(status & 0x7F)<<endl; //查看退出信号
    //     cout<<"core dump:"<<((status>>7) & 0x1)<<endl; //core值
    // }

    return 0;
}